package com.tanhua.server.service;


import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dubbo.api.*;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongoDb.RecommendUser;
import com.tanhua.model.mongoDb.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserThreadLocal;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Pan Rundong
 * @Date 2023-02-27 20:00
 * @Desc 交友service
 */
@Service
public class TanhuaService {
    @DubboReference(version = "1.0.0")
    private RecommendUserApi recommendUserApi;
    @DubboReference(version = "1.0.0")
    private UserInfoApi userInfoApi;
    @DubboReference
    private QuestionApi questionApi;
    @Autowired
    private HuanXinTemplate huanXinTemplate;
    @Value("${tanhua.default.recommend.users}")
    private String recommendUsers;
    @DubboReference
    private UserLikeApi userLikeApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private MessagesService messagesService;
    @DubboReference(version = "1.0.0")
    private UserLocationApi userLocationApi;
    @DubboReference
    private VisitorsApi visitorsApi;
    /**
     * 今日佳人
     *
     * @param
     * @return com.tanhua.model.mongoDb.RecommendUser
     * @Author Pan Rundong
     */
    public TodayBest todayBest() {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();
        //2.调用api
        RecommendUser recommendUser =  recommendUserApi.todayBest(userId);

        //3.判断是否有推荐用户
        if (recommendUser == null) {
            //3.1无，设置默认用户
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99D);
        }
        //4.查询推荐用户信息
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());

        //5.封装vo
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);

        //6.返回数据
        return todayBest;
    }


    //查询分页推荐好友列表
    public PageResult recommendation(RecommendUserDto dto) {
        //1、获取用户id
        Long userId = UserThreadLocal.getUserId();
        //2、调用recommendUserApi分页查询数据列表（PageResult -- RecommendUser）
        PageResult pr = recommendUserApi.queryRecommendUserList(dto.getPage(),dto.getPagesize(),userId);
        //3、获取分页中的RecommendUser数据列表
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        //4、判断列表是否为空
        if(items == null || items.size() <=0) {
            return pr;
        }
        //5、提取所有推荐的用户id列表
        List<Long> ids = CollUtil.getFieldValues(items, "userId", Long.class);
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());
        //6、构建查询条件，批量查询所有的用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, userInfo);
        //7、循环推荐的数据列表，构建vo对象
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser item : items) {
            UserInfo info = map.get(item.getUserId());
            if(info!=null) {
                TodayBest vo = TodayBest.init(info, item);
                list.add(vo);
            }
        }
        //8、构造返回值
        pr.setItems(list);
        return pr;
    }



    /**
     * 首页推荐-自用
     *
     * @param dto
     * @return com.tanhua.model.vo.PageResult
     * @Author Pan Rundong
     */
    public PageResult recommendation2(RecommendUserDto dto) {
        //1.获得用户Id
        Long userId = UserThreadLocal.getUserId();
        //2.查询recommend表，得到分页后List
        List<RecommendUser> userList = recommendUserApi.getPage(userId);

        //3.获取推荐用户ids
        List<Long> ids = new ArrayList<>();
        userList.forEach((item)->{
            ids.add(item.getUserId());
        });

        //4.获取条件信息
        Integer age = dto.getAge();
        String gender = dto.getGender();
        //5.调用userInfoApi
        Page<UserInfo> page = userInfoApi.recommendationPage(dto.getPage(), dto.getPagesize(),
                ids, age, gender);
        //5.1 存入Map
        List<UserInfo> records = page.getRecords();
        Map<Long, UserInfo> map = new HashMap<>();
        records.forEach((item)->{
            map.put(item.getId(), item);
        });
        //6.构建PageResult
        PageResult pageResult = new PageResult();
        pageResult.setItems(records);
        pageResult.setPage((int) page.getCurrent());
        pageResult.setCounts(records.size());
        pageResult.setPagesize((int) page.getSize());
        pageResult.setPages(records.size()/(int) page.getSize()+1);

        //7.如果查不到，返回分页信息
        if (records == null || records.size() == 0) {
            return pageResult;
        }

        //8.构建TodayBest List
        List<TodayBest> list = new ArrayList<>();
        userList.forEach((recommendUser) -> {
            UserInfo userInfo = map.get(recommendUser.getUserId());
            if (userInfo != null) {
                //1.创建TodayBest对象
                TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
                list.add(todayBest);
            }
        });

        pageResult.setItems(list);
        //8.返回
        return pageResult;
    }

    /**
     * 根据佳人Id获取对应信息
     *
     * @param userId
     * @return com.tanhua.model.vo.TodayBest
     * @Author Pan Rundong
     */
    public TodayBest getById(Long userId) {
        //1.根据Id查询佳人信息
        Long toUserId = UserThreadLocal.getUserId();
        RecommendUser recommendUser = recommendUserApi.findById(toUserId, userId);

        //2.根据Id查询用户信息
        UserInfo userInfo = userInfoApi.findById(userId);

        //3.添加访客记录
        Visitors visitors = new Visitors();
        visitors.setUserId(userId);
        visitors.setVisitorUserId(toUserId);
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitors.setScore(recommendUser.getScore());
        visitorsApi.save(visitors);

        //4.封装vo信息并返回
        TodayBest todayBest = TodayBest.init(userInfo, recommendUser);
        return todayBest;
    }

    /**
     * 查看佳人问题
     *
     * @param userId
     * @return java.lang.String
     * @Author Pan Rundong
     */
    public String getQuestion(Long userId) {
        //1.调用api查询用户信息，获取问题
        Question question = questionApi.getById(userId);
        //2.如果为null返回默认
        return question == null ? "你喜欢Java嘛" : question.getTxt();
    }

    /**
     * 回复陌生人信息
     *
     * @param userId
     * @param reply
     * @return void
     * @Author Pan Rundong
     */
    public void reply(Long userId, String reply) {
        //1.获取当前用户Id
        Long currentUserId = UserThreadLocal.getUserId();
        //2.获取对方用户环信Id，存储信息并调用template
        UserInfo userInfo = userInfoApi.findById(currentUserId);
        Map map = new HashMap(10);
        map.put("userId",currentUserId);
        map.put("huanXinId", Constants.HX_USER_PREFIX+currentUserId);
        map.put("nickname",userInfo.getNickname());
        map.put("strangerQuestion",getQuestion(userId));
        map.put("reply",reply);
        String message = JSON.toJSONString(map);

        Boolean aBoolean = huanXinTemplate.sendMsg(Constants.HX_USER_PREFIX + userId, message);

        if(!aBoolean) {
            throw  new BusinessException(ErrorResult.error());
        }
    }

    /**
     * 探花推荐
     *
     * @param
     * @return java.util.List<com.tanhua.model.vo.TodayBest>
     * @Author Pan Rundong
     */
    public List<TodayBest> cards() {
        //1.调用Api查询推荐
        Long userId = UserThreadLocal.getUserId();
        List<RecommendUser> todayBests = recommendUserApi.cards(userId,10);

        //2.如果为空，构建对象
        if (todayBests.isEmpty()) {
            todayBests = new ArrayList<>();
            String[] recommendDefault = recommendUsers.split(",");
            for (String recommendId : recommendDefault) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setToUserId(userId);
                recommendUser.setUserId(Long.valueOf(recommendId));
                recommendUser.setScore(Math.random()*30+60);
                todayBests.add(recommendUser);
            }
        }

        //获得
        List<Long> userIds = CollUtil.getFieldValues(todayBests, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);

        List<TodayBest> todayBestList = todayBests.stream().map((recommend)->{
            TodayBest todayBest = TodayBest.init(map.get(recommend.getUserId()), recommend);
            return todayBest;
        }).collect(Collectors.toList());
        return todayBestList;
    }

    /**
     * 左滑喜欢
     *
     * @param likeUserId
     * @return void
     * @Author Pan Rundong
     */
    public void love(Long likeUserId) {
        //1.调用Api存储喜欢信息
        Long userId = UserThreadLocal.getUserId();
        Boolean flag = userLikeApi.saveOrUpdate(userId, likeUserId, true);

        //2.判断是否存储成功
        if (!flag) {
            //存储失败
            throw new BusinessException(ErrorResult.error());
        }

        //存储成功
        //3.存入Reids缓存，同时删除不喜欢信息
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + userId, likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + userId, likeUserId.toString());

        //4.判断是否双向喜欢，是则加为好友
        if (isLike(likeUserId, userId)) {
            messagesService.contacts(likeUserId);
        }

    }

    /**
     * 右滑不喜欢
     *
     * @param likeUserId
     * @return void
     * @Author Pan Rundong
     */
    public void unLove(Long likeUserId) {
        //1.调用Api存储不喜欢信息
        Long userId = UserThreadLocal.getUserId();
        Boolean flag = userLikeApi.saveOrUpdate(userId, likeUserId, false);

        //2.判断是否存储成功
        if (!flag) {
            //存储失败
            throw new BusinessException(ErrorResult.error());
        }

        //存储成功
        //3.存入Reids缓存，同时删除喜欢信息
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY + userId, likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY + userId, likeUserId.toString());

//        4.判断是否双向喜欢，是则删除好友
        if (isLike(likeUserId, userId)) {
            messagesService.removeContacts(likeUserId);
        }
    }

    /**
     * 判断是否双向喜欢
     *
     * @param userId
     * @param likeUserId
     * @return java.lang.Boolean
     * @Author Pan Rundong
     */
    public Boolean isLike(Long userId, Long likeUserId) {
        String key = Constants.USER_LIKE_KEY + userId;
        return redisTemplate.opsForSet().isMember(key, likeUserId.toString());
    }

    /**
     * 搜附近的人
     *
     * @param gender
     * @param distance
     * @return java.util.List<com.tanhua.model.vo.NearUserVo>
     * @Author Pan Rundong
     */
    public List<NearUserVo> search(String gender, Double distance) {
        //1.获取当前用户Id
        Long userId = UserThreadLocal.getUserId();

        //2.调用Api获取符合条件的人
        List<Long> ids = userLocationApi.search(distance, userId);
        if (ids == null) {
            return new ArrayList<>();
        }

        //3.获取对应userId，查询用户信息
        ids.remove(userId);
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(ids, userInfo);

        //4.封装vo
        List<NearUserVo> voList = new ArrayList<>();
        for (Long id : ids) {
            UserInfo user = userInfoMap.get(id);
            if (user != null) {
                NearUserVo vo = NearUserVo.init(userInfo);
                voList.add(vo);
            }
        }

        //5.返回
        return voList;
    }
}
